
enum abil_state  { casting, cooldown, travel, dotted, inactive };
enum err_msg     { out_of_mana, obstacle, too_far_away1, too_far_away2, is_on_cooldown, too_many_cooldowns };
enum dot_index   { fire, biological, acid, radioactive };
enum event_state { JUMPS, LANDS, MOVES, STOPS, USE_ITEM, ABILITY };
/* timer_state */
struct timer_state
{
    timer_state() { reset();}
    void reset() { ticks_left = 0; state = inactive; }
    abil_state state;
    float delay; // either cooldown or cast time
    short emit, abil, target;
    char ticks_left;
};
/* ABILITIES MASK */
#define CONIC   (1 << 0)
#define BELL    (1 << 1)
#define CHAIN   (1 << 2)
#define MISSILE (1 << 3)

// requires target, always land on it
// CHAR MASK ---- MOVING RUNNING FALLING STUNNED INVISIBLE STEALTH KNOCKED DEAD BLINDED SNARED
#ifndef LOLILIL
#define MOVING    (1 << 0)
#define RUNNING   (1 << 1)
#define FALLING   (1 << 2)
#define STUNNED   (1 << 3)
#define INVISIBLE (1 << 4)
#define STEALTH   (1 << 5)
#define KNOCKED   (1 << 6)
#define DEAD      (1 << 7)
#define BLINDED   (1 << 8)
#define SNARED    (1 << 9)
#endif

struct ability
// totally changed my mind on how making abilities after trying to rethink diablo 3 skill system.
{
    float cooltime;       // < 0, instant then cooldown, > 0, charge
    char
        mask,     
        range,    // 0 = self emit
        radius,   // 0 = single target (might be mutually exclusive with self emit)
        velocity, // 0 = instant landing on target
        ticks,    // 0 = no dot
        cost;
    short    
        experience,
        dmg,
        dmg_tick;
    bool on_cooldown;
    ability
    (
     float _cooltime = 1.0f,
     char _mask = 0,
     char _range = 0,
     char _radius = 0,
     char _velocity = 0,
     char _ticks = 0,
     char _cost = 0,
     short _experience = 0,
     short _dmg = 1,
     short _dmg_tick = 0,
     bool _on_cooldown = false
    ):
    cooltime    (_cooltime),
    mask        (_mask),
    range       (_range),
    radius      (_radius),
    velocity    (_velocity),
    ticks       (_ticks),
    cost        (_cost),
    experience  (_experience),
    dmg         (_dmg),
    dmg_tick    (_dmg_tick),
    on_cooldown (_on_cooldown)
    {}
};
// blog post:
// design matters more when programming. design must be fixed and appropriately doable in code.
// conclusion : time spent designing is worth 10 fold the time spent coding.
struct character_s
{
    short
        mask,
        target,
        moving_speed_default,   // might be a int, since it's multiplier
        stealth_range,          // the smaller the stealthier
        mana,                   // might, mana, energy, etc
        life,                   // duh
        defense;                // percentage of damage reduction, negative
    character_s
    (
     short _mask = 0,
     short _moving_speed_default = 1,
     short _stealth_range = 10,
     short _mana = 100,
     short _life = 10000,
     short _defense = 10000
     ):
    mask(_mask),
    moving_speed_default(_moving_speed_default),
    stealth_range(_stealth_range),
    mana(_mana),
    life(_life),
    defense(_defense),
    target(0)
    {
        FOR(3)
            abilids.push_back(i);
    }
    std::vector <short> abilids;
};


struct buff
{
    float tick;
};
namespace game
{
    std::vector <std::string>CharNames;
    std::vector <character_s>Characters;
    std::map <std::string, short> CharIds;
    
    std::vector<ability> Abilities;
    std::vector<string> AbilNames;
    std::map<string, short> AbilIds;

    object_pool<timer_state> Timers;
    void load_abilities();
    void diagnose();

    void update();
    string inspect_cast(short emit, short abil, short target); 
    
    void set_target (short emit, short target);
    void cast_cmd   (short emit, short abil, short target);
    void cast_start (short emit, short abil, short target);
    void cast_launch(short emit, short abil, short target);
    void cast_land  (short emit, short abil, short target);
    void cast_dot   (short emit, short abil, short target);

    void damage_msg(short emit, short target, short dmg);
    void error_message (err_msg);
    //Vec3 click_position;
    Vec3 click_position, projectile;
}
